#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cassert>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "Tast.h++"
#define NUM 5
using namespace std;
// 读入数据
int waitCommand(int waitfd, bool quit)
{

    uint32_t command = 0;
    ssize_t s = read(waitfd, &command, sizeof(command));
    if (s == 0)
    {
        quit = true;
        return -1;
    }
    assert(s = sizeof(uint32_t));
    return command;
}
// 写入数据
void sendAndWakeup(pid_t who, int fd, uint32_t command)
{
    while (fd, &command, sizeof(command))
        ;
    cout << "main process: call process " << who << " execute " << desc[command] << " through " << fd << endl;
}

int main()
{
    load();
    vector<pair<pid_t, int>> slots; // 多个命令，pid_t 子进程id，文件描述符
    // unordered_map<>
    for (int i = 0; i < NUM; i++)
    {
        int pipefd[2] = {0};
        int n = pipe(pipefd); // 管道
        assert(n != 0);
        (void)n; // 使用
        pid_t id = fork();
        assert(id >= 0);
        if (id == 0)
        {
            close(pipefd[1]); // 关闭写
            // 当代命令
            while (true)
            {
                bool quit = false; // command为0时，直接退出
                int command = waitCommand(pipefd[0], quit);
                if (quit == true)
                {
                    exit(1);
                }
                if (command >= 0 && command < handlerSize())
                {
                    callbacks[command](); // 执行命令
                }
                else
                {
                    cout << "非法command" << endl;
                }
            }
        }
        // 关闭文件
        close(pipefd[0]);
        slots.push_back(pair<pid_t, int>(id, pipefd[1])); // 插入进程

        if (id > 0)
        {
            close(pipefd[0]);
            srand((unsigned long)time(nullptr) ^ getpid() ^ 23323123123L);
            while (true)
            {
                // int command = rand() % handlerSize();

                // int choice = rand() % slots.size();
                // sendAndWakeup(slots[choice].first, slots[choice].second, command);
                // sleep(1);
                int select;
                int command;
                cout << "############################################" << endl;
                cout << "#   1. show funcitons      2.send command  #" << endl;
                cout << "############################################" << endl;
                cout << "Please Select> ";
                cin >> select;
                if (select == 1)
                    showHandle();
                else if (select == 2)
                {
                    cout << "Enter Your Command> ";
                    // 选择任务
                    cin >> command;
                    // 选择进程
                    int choice = rand() % slots.size();
                    // 把任务给指定的进程
                    sendAndWakeup(slots[choice].first, slots[choice].second, command);
                }
                else
                {
                    ;
                }
            }
        }
        // 关闭子进程
        for (const auto &slot : slots)
        {
            close(slot.second);
        }

        // 回收所有的子进程信息
        for (const auto &slot : slots)
        {
            waitpid(slot.first, nullptr, 0);
        }
    }
}
